package xyz.liut.autolaunch;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.TimePickerDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.TimePicker;

import androidx.annotation.RequiresApi;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import xyz.liut.logcat.L;
import xyz.liut.logcat.LogHandler;

/**
 * Create by liut on 20-10-27
 */
public class MainActivity extends Activity {

    private static final String TAG = "MainActivity";

    private EditText etPkg, etTiming;
    private Switch swRoot, swTiming;

    private SpTool spTool;

    private LogHandler logHandler;
    private Handler handler;

    private TextView tvLog;

    private TimePicker timePicker;

    private TimePickerDialog timePickerDialog;

    private LinearLayout llTime;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvLog = findViewById(R.id.tv_log);
        handler = new Handler(Looper.getMainLooper());

        spTool = SpTool.getDefault(this);

        llTime = findViewById(R.id.ll_time);

        etPkg = findViewById(R.id.et_pkg);
        etTiming = findViewById(R.id.et_timing);

        swRoot = findViewById(R.id.sw_root);
        swTiming = findViewById(R.id.sw_timing);

        Button btSave = findViewById(R.id.bt_save);
        Button btLaunch = findViewById(R.id.bt_launch);

        // 添加计时
        findViewById(R.id.bt_add_time).setOnClickListener(v -> timePickerDialog.show());
        // 长安清空
        findViewById(R.id.bt_add_time).setOnLongClickListener(v -> {
            spTool.save(Constants.Default.KEY_TIMES, "");
            llTime.removeAllViews();
            return true;
        });

        // 保存
        btSave.setOnClickListener(v -> save());

        // 启动
        btLaunch.setOnClickListener(v -> LaunchTool.launch(MainActivity.this, etPkg.getText().toString().trim(), swRoot.isChecked()));

        // log
        setLog();

        initDialog();

        // 恢复设定
        loadData();

    }

    @SuppressLint("SetTextI18n")
    private void initDialog() {
        timePickerDialog = new TimePickerDialog(this,
                (view, hourOfDay, minute) -> addTime(hourOfDay + ": " + minute),
                0,
                0,
                true);
    }

    private void loadData() {
        // 恢复
        String pkg = spTool.get(Constants.Default.KEY_PKG);
        if (!TextUtils.isEmpty(pkg)) {
            int timingValue;
            try {
                timingValue = Integer.parseInt(spTool.get(Constants.Default.KEY_TIMING, "0"));
            } catch (Exception e) {
                return;
            }
            boolean swTimingValue = Boolean.parseBoolean(spTool.get(Constants.Default.KEY_SW_TIMING, "false"));
            boolean isRoot = Boolean.parseBoolean(spTool.get(Constants.Default.KEY_ROOT, "false"));
            String timeList = spTool.get(Constants.Default.KEY_TIMES);

            String[] timeArray = timeList.split("#");
            for (String time : timeArray) {
                if (!TextUtils.isEmpty(time))
                    addTime(time);
            }

            etPkg.setText(pkg);
            etTiming.setText(String.valueOf(timingValue));
            swRoot.setChecked(isRoot);
            swTiming.setChecked(swTimingValue);

            setup();
        }
    }

    private void addTime(String time) {
        TextView textView = new TextView(MainActivity.this);
        textView.setText(time);
        llTime.addView(textView);
    }

    private void save() {
        spTool.save(Constants.Default.KEY_PKG, etPkg.getText().toString().trim());
        spTool.save(Constants.Default.KEY_TIMING, etTiming.getText().toString().trim());
        spTool.save(Constants.Default.KEY_ROOT, String.valueOf(swRoot.isChecked()));
        spTool.save(Constants.Default.KEY_SW_TIMING, String.valueOf(swTiming.isChecked()));

        int count = llTime.getChildCount();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < count; i++) {
            TextView textView = (TextView) llTime.getChildAt(i);
            String time = textView.getText().toString();
            builder.append(time);
            if (i != count - 1) {
                builder.append("#");
            }
        }
        spTool.save(Constants.Default.KEY_TIMES, builder.toString());

        // 如果未忽略则弹窗提醒
        if (swTiming.isChecked() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !hasIgnoredBatteryOptimization()) {
            new AlertDialog
                    .Builder(this)
                    .setTitle("忽略电池优化")
                    .setMessage("忽略电池优化会使本软件的定时功能更加稳定， 并不会增加耗电量， 请在接下来的提示中选择允许。")
                    .setPositiveButton("确定", (dialog, which) -> ignoreBatteryOptimization())
                    .setNegativeButton("取消", null)
                    .setOnDismissListener(dialog -> setup())
                    .show();
        } else {
            setup();
        }
    }

    private void setLog() {
        logHandler = (level, tag, msg) -> handler.post(() -> {
                    tvLog.append(tag + ": " + msg);
                    tvLog.append("\n");
                }
        );
        L.getDefault().addHandler(logHandler);

        tvLog.setOnLongClickListener(v -> {
            tvLog.setText("");
            //noinspection ResultOfMethodCallIgnored
            new File(App.LOG_FILE).delete();
            return true;
        });

        File file = new File(App.LOG_FILE);
        if (file.length() > 100 * 1024) {
            //noinspection ResultOfMethodCallIgnored
            file.delete();
        }
        try {
            if (file.exists()) {
                FileInputStream fis = new FileInputStream(file);
                final byte[] bytes = new byte[(int) file.length() - 1];
                int res = fis.read(bytes);
                fis.close();
                if (res == file.length() - 1) {
                    tvLog.setText(new String(bytes));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 设置定时
    private void setup() {
        ExecJob.setup(MainActivity.this);
    }


    /**
     * 是否已经忽略电池优化
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    public boolean hasIgnoredBatteryOptimization() {
        try {
            PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
            boolean hasIgnored = powerManager.isIgnoringBatteryOptimizations(this.getPackageName());
            Log.d(TAG, "ignoreBatteryOptimization() called with hasIgnored = " + hasIgnored);
            return hasIgnored;
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
    }

    /**
     * 发起忽略
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    public void ignoreBatteryOptimization() {
        try {
            @SuppressLint("BatteryLife")
            Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
            intent.setData(Uri.parse("package:" + getPackageName()));
            startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        L.getDefault().removeHandler(logHandler);
    }

}
